package com.punch.oauth.config;


import com.punch.oauth.component.JwtTokenEnhancer;
import com.punch.oauth.service.impl.RedisClientDetailsService;
import com.punch.oauth.service.impl.UaaUserServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * 认证服务器配置
 * Created by macro on 2020/6/19.
 */

@Configuration
@EnableAuthorizationServer
public class Oauth2ServerConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private RedisClientDetailsService clientDetailsService;

    @Resource
    private AuthenticationManager authenticationManager;

    @Resource
    private JwtTokenEnhancer jwtTokenEnhancer;

    @Resource
    private WebResponseExceptionTranslator webResponseExceptionTranslator;

    @Resource
    private UaaUserServiceImpl userDetailsService;

    @Resource
    private JwtAccessTokenConverter JwtAccessTokenConverter;

    /**
     * 配置被允许访问此认证服务器的客户端信息
     * 1.内存方式
     * 2. 数据库方式
     *
     * @param clients 客户端
     * @throws Exception
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.withClientDetails(clientDetailsService);
        clientDetailsService.loadAllClientToCache();
    }


    /**
     * 关于认证服务器端点配置
     *
     * @param endpoints
     * @throws Exception
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        TokenEnhancerChain enhancerChain = new TokenEnhancerChain();
        List<TokenEnhancer> delegates = new ArrayList<>();
        delegates.add(jwtTokenEnhancer);
        delegates.add(JwtAccessTokenConverter);
        enhancerChain.setTokenEnhancers(delegates); //配置JWT的内容增强器
        endpoints.exceptionTranslator(webResponseExceptionTranslator);
        endpoints.authenticationManager(authenticationManager) //password 要这个 AuthenticationManager 实例
                .userDetailsService(userDetailsService) //配置加载用户信息的服务
                .accessTokenConverter(JwtAccessTokenConverter)
                .tokenEnhancer(enhancerChain);

    }


    /**
     * 对应于配置AuthorizationServer安全认证的相关信息，创建ClientCredentialsTokenEndpointFilter核心过滤器
     *
     * @param security
     */
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) {
        security
                .tokenKeyAccess("isAuthenticated()")
                .checkTokenAccess("permitAll()")
                //让/oauth/token支持client_id以及client_secret作登录认证
                .allowFormAuthenticationForClients();
    }

}